package com.yun.wemedia.service.impl;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.heima.model.article.dtos.ApArticleDTO;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.dtos.WmNewsDTO;
import com.heima.model.wemedia.dtos.WmNewsPageDTO;
import com.heima.model.wemedia.dtos.WmTakenDownDTO;
import com.heima.model.wemedia.pojos.WmMaterial;
import com.heima.model.wemedia.pojos.WmNews;
import com.heima.model.wemedia.pojos.WmNewsMaterial;
import com.heima.utils.common.UserContext;
import com.yun.feign.article.ArticleClient;
import com.yun.wemedia.mapper.*;
import com.yun.wemedia.service.WmNewsAutoScanService;
import com.yun.wemedia.service.WmNewsService;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Excell
 * @description 针对表【wm_news(自媒体图文内容信息表)】的数据库操作Service实现
 * @createDate 2025-07-23 08:25:36
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class WmNewsServiceImpl extends ServiceImpl<WmNewsMapper, WmNews>
        implements WmNewsService {

    private final WmNewsMaterialMapper wmNewsMaterialMapper;

    private final WmMaterialMapper wmMaterialMapper;

    private final WmNewsAutoScanService wmNewsAutoScanService;

    private final ArticleClient articleClient;

    private final WmUserMapper wmUserMapper;

    private final WmChannelMapper wmChannelMapper;

    private final WmNewsMapper wmNewsMapper;

    private final RabbitTemplate rabbitTemplate;

    @Override
    @Transactional
    public ResponseResult queryList(WmNewsPageDTO wmNewsPageDTO) {
        // 获取当前用户 ID
        Long userId = UserContext.getUser();
        if (userId == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.AP_USER_DATA_NOT_EXIST);
        }

        // 参数校验
        if (wmNewsPageDTO == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        // 构建查询条件
        LambdaQueryWrapper<WmNews> queryWrapper = new LambdaQueryWrapper<>();

        queryWrapper.eq(wmNewsPageDTO.getStatus() != null, WmNews::getStatus, wmNewsPageDTO.getStatus())
                .like(StringUtils.isNotBlank(wmNewsPageDTO.getKeyword()), WmNews::getTitle, wmNewsPageDTO.getKeyword())
                .eq(wmNewsPageDTO.getChannelId() != null, WmNews::getChannelId, wmNewsPageDTO.getChannelId())
                .ge(wmNewsPageDTO.getBeginPubDate() != null, WmNews::getCreatedTime, wmNewsPageDTO.getBeginPubDate())
                .le(wmNewsPageDTO.getEndPubDate() != null, WmNews::getCreatedTime, wmNewsPageDTO.getEndPubDate())
                .eq(WmNews::getUserId, userId);

        // 分页查询
        Page<WmNews> page = new Page<>(wmNewsPageDTO.getPage(), wmNewsPageDTO.getSize());
        Page<WmNews> resultPage = this.page(page, queryWrapper);

        // 构建返回结果
        PageResponseResult response = new PageResponseResult(
                (int) resultPage.getCurrent(),
                (int) resultPage.getSize(),
                (int) resultPage.getTotal()
        );
        response.setData(resultPage.getRecords());

        return response;
    }

    /**
     * @description: 文章提交或保存
     * @title: submitOrUpdate
     * @param: [wmNewsDTO]
     */
    @Override
    @GlobalTransactional
    public void submitOrUpdate(WmNewsDTO wmNewsDTO) {
        log.info("Seata全局事务id=================>{}", RootContext.getXID());
        // WmNewsDTO要进行校验是否为空值
        if (wmNewsDTO == null) {
            return;
        }

        // 1. 判断文章 ID 是否存在
        WmNews wmNews = this.getById(wmNewsDTO.getId());
        if (wmNews != null) {
            // 2. 查询与该文章关联的素材记录
            List<WmNewsMaterial> wmNewsMaterials = wmNewsMaterialMapper.selectList(
                    new LambdaQueryWrapper<WmNewsMaterial>()
                            .eq(WmNewsMaterial::getNewsId, wmNews.getId())
            );

            // 3. 提取 ID 并批量删除
            if (wmNewsMaterials != null && !wmNewsMaterials.isEmpty()) {
                List<Integer> ids = wmNewsMaterials.stream()
                        .map(WmNewsMaterial::getId)
                        .collect(Collectors.toList());
                wmNewsMaterialMapper.deleteBatchIds(ids);
            }
        }

        // 3.将文章表中的数据进行修改或进行保存
        wmNews = saveNews(wmNewsDTO);

        // 4.重新将文章素材之间的关系保存到文章素材关联表中
        List<String> images = Arrays.asList(wmNews.getImages().split(","));


        // 5.判断文章的封面是自动还是指定
        // 6.指定，直接将封面图片和素材之间的关系保存到文章素材表中
        if (wmNewsDTO.getImages() != null && !images.isEmpty() && wmNewsDTO.getType() != -1) {
            saveNewsMaterial(wmNews, wmNewsDTO.getImages(), 1);
        } else if (wmNewsDTO.getImages() != null && !images.isEmpty()) {
            // 7.自动，将文章中的图片进行解析存放到List集合中，然后根据规则将封面图片和素材之间的关系保存到文章素材表中
            if (images.size() >= 3) {
                saveNewsMaterial(wmNews, images.stream().limit(3).collect(Collectors.toList()), 0);
                wmNews.setType(3);
                wmNewsMapper.updateById(wmNews);
            } else {
                saveNewsMaterial(wmNews, images.stream().limit(1).collect(Collectors.toList()), 0);
                wmNews.setType(1);
                wmNewsMapper.updateById(wmNews);
            }
        } else {
            saveNewsMaterial(wmNews, images, 0);
        }
        // 审核，保存完回写id后才能进行审核
        wmNewsAutoScanService.autoScanWmNews(wmNews.getId());
    }

    /**
     * @description: 文章下架
     * @title: isDown
     * @param: [wmTakenDownDTO]
     */
    @Override
    public ResponseResult isDown(WmTakenDownDTO wmTakenDownDTO) {
        // 校验数据是否存在
        if (wmTakenDownDTO == null || wmTakenDownDTO.getId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }

        WmNews wmNews = getById(wmTakenDownDTO.getId());
        if (wmNews == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "文章不存在");
        }

        // 1.修改修改表wm_news，根据id将enable属性改为0
        boolean updated = update(null, new LambdaUpdateWrapper<WmNews>()
                .eq(WmNews::getId, wmTakenDownDTO.getId())
                .set(WmNews::getEnable, wmTakenDownDTO.getEnable())
        );

        if (!updated) {
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR, "文章更新失败");
        }

        // 2.使用mq调用接口，实现修改文章表ap_article的配置表，从而将下架属性进行修改为1
        // 根据id获取文章id

        rabbitTemplate
                .convertAndSend("article.config.direct.exchange",
                        "article.config.update",
                        wmNews.getArticleId());

        // 3.返回成功状态
        return ResponseResult.okResult("下架成功");
    }

    private void saveNewsMaterial(WmNews wmNews, List<String> images, int type) {
        int ord = 0;
        /*
         因为数据量比较少，所以不做批量处理
         * */
        for (String image : images) {

            WmMaterial wmMaterial = wmMaterialMapper.selectOne(new LambdaQueryWrapper<WmMaterial>()
                    .eq(WmMaterial::getUrl, image));

            WmNewsMaterial wmNewsMaterial = WmNewsMaterial.builder()
                    .materialId(wmMaterial.getId())
                    .newsId(wmNews.getId().longValue())
                    .type(type)
                    .ord(ord)
                    .build();

            ord++;

            wmNewsMaterialMapper.insert(wmNewsMaterial);
        }
    }

    private WmNews saveNews(WmNewsDTO wmNewsDTO) {


        List<Map<String, String>> contentList = new ArrayList<>();
        try {
            contentList = new ObjectMapper().readValue(
                    wmNewsDTO.getContent(),
                    new TypeReference<List<Map<String, String>>>() {
                    }
            );
        } catch (JsonProcessingException e) {
            throw new RuntimeException();
        }

        List<String> images = new ArrayList();
        for (Map<String, String> contentMap : contentList) {
            if ("image".equals(contentMap.get("type"))) {
                images.add((String) contentMap.get("value"));
            }
        }


        WmNews wmNews = WmNews.builder()
                .id(wmNewsDTO.getId())
                .title(wmNewsDTO.getTitle())
                .content(wmNewsDTO.getContent())
                .channelId(wmNewsDTO.getChannelId())
                .labels(wmNewsDTO.getLabels())
                .publishTime(wmNewsDTO.getPublishTime())
                .submitedTime(new Date()) // 当前时间
                .status(wmNewsDTO.getStatus())
                .type(wmNewsDTO.getType() == -1 ? 0 : wmNewsDTO.getType()) // 自动类型修正
                .images(String.join(",", images))
                .userId(UserContext.getUser().intValue())
                .createdTime(new Date())
                .articleId(IdWorker.getId())
                .enable(1) // 默认启用
                .build();


        ApArticleDTO apArticleDTO = ApArticleDTO.builder()
                .title(wmNews.getTitle())
                .content(wmNews.getContent())
                .images(wmNews.getImages())
                .authorId(UserContext.getUser().intValue())
                .authorName(wmUserMapper.selectById(wmNews.getUserId()).getName())
                .channelId(wmNews.getChannelId())
                .channelName(wmChannelMapper.selectById(wmNews.getChannelId()).getName())
                .layout(wmNews.getType() == -1 ? 0 : wmNews.getType())
                .build();

        // 远程调用
        ResponseResult result = articleClient.insert(apArticleDTO);
        Long articleId = (Long) result.getData();
        wmNews.setArticleId(articleId);

        this.save(wmNews);

        return wmNews;
    }

}




